#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
语音合成服务 - 简化版本
基于讯飞WebSocket流式语音合成API
"""

import websocket
import datetime
import hashlib
import base64
import hmac
import json
import logging
import os
import ssl
import threading
import time
from urllib.parse import urlencode
from wsgiref.handlers import format_date_time
from datetime import datetime
from time import mktime

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)


class SimpleTTSService:
    """简化的语音合成服务"""
    
    def __init__(self, app_id, api_key, api_secret):
        self.app_id = app_id
        self.api_key = api_key
        self.api_secret = api_secret
        self.audio_data = b""
        self.is_completed = False
        self.error_message = None
        
        logger.info("简化语音合成服务初始化完成")
    
    def create_auth_url(self, text, voice="xiaoyan", speed=50, volume=50, pitch=50):
        """创建认证URL"""
        url = 'wss://tts-api.xfyun.cn/v2/tts'
        
        # 生成RFC1123格式的时间戳
        now = datetime.now()
        date = format_date_time(mktime(now.timetuple()))
        
        # 拼接签名字符串
        signature_origin = "host: " + "tts-api.xfyun.cn" + "\n"
        signature_origin += "date: " + date + "\n"
        signature_origin += "GET " + "/v2/tts " + "HTTP/1.1"
        
        # 进行hmac-sha256加密
        signature_sha = hmac.new(
            self.api_secret.encode('utf-8'), 
            signature_origin.encode('utf-8'),
            digestmod=hashlib.sha256
        ).digest()
        signature_sha = base64.b64encode(signature_sha).decode(encoding='utf-8')
        
        # 构建authorization
        authorization_origin = 'api_key="%s", algorithm="%s", headers="%s", signature="%s"' % (
            self.api_key, "hmac-sha256", "host date request-line", signature_sha)
        authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
        
        # 拼接鉴权参数
        v = {
            "authorization": authorization,
            "date": date,
            "host": "tts-api.xfyun.cn"
        }
        
        # 生成完整URL
        url = url + '?' + urlencode(v)
        
        # 构建请求数据
        request_data = {
            "common": {"app_id": self.app_id},
            "business": {
                "aue": "raw",
                "auf": "audio/L16;rate=16000",
                "vcn": voice,
                "tte": "utf8",
                "speed": speed,
                "volume": volume,
                "pitch": pitch,
                "bgs": 0,
                "reg": "0",
                "rdn": "0"
            },
            "data": {
                "status": 2,
                "text": str(base64.b64encode(text.encode('utf-8')), "UTF8")
            }
        }
        
        return url, request_data
    
    def synthesize(self, text, output_file=None, voice="xiaoyan", 
                   speed=50, volume=50, pitch=50):
        """
        语音合成
        
        Args:
            text: 要合成的文本
            output_file: 输出文件路径（可选）
            voice: 发音人
            speed: 语速
            volume: 音量
            pitch: 音高
            
        Returns:
            bytes: 合成的音频数据
        """
        logger.info(f"开始语音合成: {text[:50]}...")
        
        # 重置状态
        self.audio_data = b""
        self.is_completed = False
        self.error_message = None
        
        # 创建认证URL和请求数据
        ws_url, request_data = self.create_auth_url(text, voice, speed, volume, pitch)
        
        def on_message(ws, message):
            try:
                message_data = json.loads(message)
                code = message_data.get("code", -1)
                
                if code != 0:
                    error_msg = message_data.get("message", "未知错误")
                    logger.error(f"语音合成错误: {error_msg}")
                    self.error_message = f"语音合成失败: {error_msg}"
                    self.is_completed = True
                    return
                
                # 处理音频数据
                data = message_data.get("data", {})
                if data:
                    audio_base64 = data.get("audio", "")
                    status = data.get("status", 0)
                    
                    if audio_base64:
                        # 解码音频数据
                        audio_bytes = base64.b64decode(audio_base64)
                        self.audio_data += audio_bytes
                        logger.info(f"接收到音频数据: {len(audio_bytes)} 字节")
                    
                    # 检查是否合成完成
                    if status == 2:
                        logger.info("语音合成完成")
                        self.is_completed = True
                        try:
                            ws.close()
                        except:
                            pass  # 忽略关闭时的错误
                
            except Exception as e:
                logger.error(f"处理消息异常: {e}")
                self.error_message = f"处理消息异常: {e}"
                self.is_completed = True
        
        def on_error(ws, error):
            # 只有在未完成时才设置错误
            if not self.is_completed:
                logger.error(f"WebSocket错误: {error}")
                self.error_message = f"WebSocket错误: {error}"
                self.is_completed = True
        
        def on_close(ws, close_status_code=None, close_msg=None):
            logger.info("WebSocket连接已关闭")
            self.is_completed = True
        
        def on_open(ws):
            def run():
                request_json = json.dumps(request_data)
                logger.info("开始发送文本数据进行语音合成")
                ws.send(request_json)
            
            threading.Thread(target=run).start()
        
        try:
            # 创建WebSocket连接
            websocket.enableTrace(False)
            ws = websocket.WebSocketApp(
                ws_url,
                on_message=on_message,
                on_error=on_error,
                on_close=on_close,
                on_open=on_open
            )
            
            # 运行WebSocket连接
            ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
            
            # 检查是否有错误
            if self.error_message:
                raise Exception(self.error_message)
            
            # 保存音频文件（如果指定了输出文件）
            if output_file and self.audio_data:
                with open(output_file, 'wb') as f:
                    f.write(self.audio_data)
                logger.info(f"音频文件已保存: {output_file}")
            
            logger.info(f"语音合成完成，音频大小: {len(self.audio_data)} 字节")
            return self.audio_data
            
        except Exception as e:
            logger.error(f"语音合成失败: {e}")
            raise Exception(f"语音合成失败: {e}")


def main():
    """测试函数"""
    print("=== 简化语音合成服务测试 ===")
    
    # 从配置文件加载配置
    with open('config.json', 'r', encoding='utf-8') as f:
        config = json.load(f)
    
    # 创建语音合成服务
    tts_config = config['text_to_speech']
    tts_service = SimpleTTSService(
        app_id=tts_config['app_id'],
        api_key=tts_config['api_key'],
        api_secret=tts_config['api_secret']
    )
    
    # 测试文本
    test_text = "你好，这是简化版语音合成测试"
    print(f"测试文本: {test_text}")
    
    try:
        # 合成语音
        audio_data = tts_service.synthesize(
            text=test_text,
            output_file="simple_tts_test.pcm",
            voice="xiaoyan",
            speed=50,
            volume=50,
            pitch=50
        )
        
        print(f"合成成功！音频大小: {len(audio_data)} 字节")
        print("音频文件: simple_tts_test.pcm")
        
        if len(audio_data) > 0:
            print("✅ 语音合成功能正常")
        else:
            print("❌ 语音合成失败，音频数据为空")
            
    except Exception as e:
        print(f"❌ 语音合成失败: {e}")


if __name__ == "__main__":
    main()
